1986-Club80-17, S27-32
Z80, HD64180 und Illegals im ROM-ModusDas Herz unseres kleinen Haufens Silikonmasse besteht bekanntermaßen aus einem Z80. Dieser Z80 kann über 1100 Befehle verarbeiten, von denen aber nur 694 von den Erbauern vorgesehen waren. Der Rest ist also Abfallprodukt. Nun gibt es einen neuen Prozessor, den HD64180, der Z80-kompatibel ist, aber einige Sachen mehr kann (512Kb RAM verwalten. DMA, Schnittstelle...). Nur haben die Erbauer dieses Dings leider vergessen, die Befehle des Z80 zu berücksichtigen, die nicht offiziell dokumentiert sind. Das kann böse Probleme geben, denn wenn der neue Proz auf einen ihm unbekannten Befehl trifft, macht er einen Brutalo-Reset nach 0000h, was in unserem Fall jedes Programm ins Jenseits befördert. Es wäre dies kein Problem, wenn niemand die "Illegals" bzw. die nicht dokumentierten Befehle benutzen würde, aber viele Programmierer tun es doch. Prominentes Beispiel der Editor/Assembler ZEUS (3 Illegals). Ihr könnt nun
Punkt 3 erschien mir brauchbar, bis sich ZEUS nach den Änderungen so merkwürdig benahm. Leider sind die Ersatz-Befehle für die Illegals nämlich einen kleinen Tick länger als die Illegals und das gibt big problems. Also auf zu Punkt 4! Vorraussetzung: Veränderliches RAM/ROM bei 0000h: bei jedem CP/M-fähigen Rechner der Fall. Außerdem habe ich in meinem kleinen Programm noch einiges ausgenutzt: Arnulf hett seggt1, daß RST 00h nie gebraucht wird. Also benutze man RST 00h für etwas anderes. In diesem Fall bot sich ein Banking an, das Helmuts alten Banker simuliert. Verfahrensweise: Der Speicher von 8000h-ffffh wird als Common 1 definiert und je nach gewünschter Bank wird der Offset von Common 1 neu gesetzt. Bank 0 ist die normale Bank, also sind dann Interrupts erlaubt. Ansonsten werden die Interrupts gesperrt. Die Bank-Nr. wird vor dem RST 00h in A geladen. Mein kleiner IIs kennt ein Parallel-RAM. D.h. Neben Tastatur. Bildschirm etc., die ja memory-mapped-I/O sind, gibt es einen RAM-Bereich von 3400h-3fffh. Je nach Wunsch kann ich nun entweder Ein-/Ausgaben vornehmen oder in diesem Extra-RAM einige zusätzliche Programme laufen lassen. Wiederum müßte jeder TRS80-CP/M-Rechner irgendetwas in der Richtung haben. Nun versteht Ihr auch, warum ich in der Überschrift von "ROM-Modus" sprach. Der ganze Kram klappt bei CP/M in dieser Form nicht. Dafür andere Lösungen zu suchen, überlasse ich den CP/M-Freaks. Zu guter Letzt kann ich auch das ROM/RAM überschreiben (s. wiederum CP/M-fähige Rechner). Da sich in dem ROM allerhand Müll angesammelt hat kann man gewisse Teile ohne Skrupel killen, was ich auch getan habe. Mit diesen ganzen Einschränkungen wird das Programm zwar sehr auf eine Maschine festgelegt, aber wer wird sich schon einen HD64180 anschaffen? Wohl doch nur Leute, die sowieso am Satteln sind und bei deren Drahtansammlungen nicht viel vom TRS80 übrig geblieben ist. Noch kurz zum eigentlichen Programm: Der erste Teil ist nur der Ansprung der Routine von 0C00h aus. Der zweite Teil ist ein Ausgang aus der Routine, bei dem die Interrupts ausgeschaltet bleiben. Die anderen Ein/Aus-Routinen stellt OVL3/SYS aus dem Gdos 2.4 zur Verfügung. Der dritte Teil ist derjenige, der beim Aufruf die Routine ins Parallel-RAM bringt. Danach folgt die eigentliche Routine, die im gegenwärtigen Zustand noch nicht mal 100h Bytes lang ist. Sie berücksichtigt alle Illegals, die in einen Artikel der "data welt" in Mai/Juni 1986 erwähnt wurden. Die HD64180-spezifischen Befehle IN0/OUT0 wurden über DBs realisiert, weil mein alter ZEUS sie natürlich nicht kennt. Der Programmierstil ist leider sehr "unschön", wie mein Prof sagen würde, vor allem aufgrund der vielen Patches direkt im Programmablauf, aber es tut seinen Dienst. Gerald Schröder Hardware: Helmut Bernhardt Literatur: "TAV’s Z80 Tuning" aus "data welt" 5 und 6 ’86 Z80-Reference-Manual00001 ; Error-Trap für Genie IIs mit HD64180 00002 ; Weihnachten ’86 by Gerald Schröder 00003 00004 06A0 00005 pramon EQU 06a0h ;schaltet Par.-RAM ein 06AB 00006 pramoff EQU 06abh ;schaltet Par.-RAM aus 00007 00008 00009 ; 00010 00011 ; 0000: Ansprung Error-Trap und RST 00h 00012 0000 00013 ORG 0 0000 CDA006 00014 CALL pramon ;Par.-RAM ein 0003 C30034 00015 JP routin-offset ;anspringen 00016 00017 00018 ; 00019 00020 ; neuer Ausgang: Par.-RAM aus und Interrupts 00021 ; bleiben disabled 00022 06D2 00023 ORG 06d2h 06D2 DBFE 00024 prama IN A,(0feh) 06D4 CB87 00025 RES 0,A 06D6 D3FE 00026 OUT (0feh),A 06D8 F1 00027 POP AF 06D9 C9 00028 RET 00029 00030 00031 ; 00032 00033 ; Initialisierungsroutine 00034 5200 00035 ORG 5200H 5200 3E80 00036 start LD A,80h ;Common 1 ab 8000h 5202 ED 00037 DB 0edh,39h,3ah ;setzen (OUT0 (3ah),A) 00038 5205 CDA006 00039 CALL pramon ;Par.-RAM ein 5208 211652 00040 LD HL,routin ;Routine 520B 110034 00041 LD DE,routin-offset ;dorthin 520E 01C900 00042 LD BC,ende-routin ;übertragen 5211 EDB0 00043 LDIR 5213 C3AB06 00044 JP pramoff ;Par.-RAM aus und ab 00045 00046 00047 ; 00048 00049 ; Routine im Par.-RAM für Error-Trap und RST 00h 00050 ; bei Error: fehlende Codes simulieren 00051 ; bei RST 00h: Bank A einschalten 00052 1E16 00053 offset EQU $-3400h 5216 F5 00054 routin PUSH AF 5217 ED 00055 DB 0edh,38h,34h ;IN0 A,(34h) 521A CB7F 00056 BIT 7,A ;TRAP gesetzt? 521C 2010 00057 JR NZ,illopc ;ja, illegaler Opcode 00058 00059 ;******************************* 00060 ;* Banking; Bank A einschalten * 00061 ;******************************* 00062 521E F1 00063 POP AF 521F F5 00064 PUSH AF ;retten 5220 07 00065 RLCA 5221 07 00066 RLCA ;korr. Offset erzeugen 5222 07 00067 RLCA ;(Basis Common 1 neu) 5223 ED 00068 DB 0edh,39h,38h ;OUT0 (38h),A 5226 B7 00069 OR A ;Bank 0? 5227 C2D206 00070 JP NZ,prama ;nein, keine Interrupts 522A F1 00071 POP AF 522B C3AB06 00072 JP pramoff ;Interrupts ein 00073 00074 00075 00076 ;********************************* 00077 ;* illegaler Opcode: simulieren * 00078 ;********************************* 00079 522E CBBF 00080 illopc RES 7,A ;TRAP löschen 5230 ED 00081 DB 0edh,39h,34h ;OUT0 (34h),A 5233 322534 00082 LD (ufo-offset),A ;UFO retten 5236 F1 00083 POP AF ;A vom Stack 5237 E3 00084 EX (SP),HL ;HL mit Err.-Adr. tausch 5238 F5 00085 PUSH AF ;A wieder retten 5239 C5 00086 PUSH BC ;BC als Hilfsregister 523A 3E00 00087 LD A,0 ;UFO 523B 00088 ufo EQU $-1 523C CB77 00089 BIT 6,A ;gesetzt? 523E 2801 00090 JR Z,nosub ;nein, Opc. direkt davor 5240 2B 00091 DEC HL 5241 2B 00092 nosub DEC HL ;Zeiger auf ill. Opc. 5242 7E 00093 LD A,(HL) ;laden 5243 47 00094 LD B,A ;und retten 5244 FECB 00095 CP 0cbh ;CBxx? (SLIA) 5246 23 00096 INC HL ;Zeiger weiter 5247 7E 00097 LD A,(HL) ;2. Byte laden 5248 200F 00098 JR NZ,ddfd ;nein, Oper. mit IX/Y 00099 00100 ;*********************************** 00101 ;* illegaler Opcode; CBxx = SLIA x * 00102 ;*********************************** 00103 524A D620 00104 SUB 20h ;korrigieren 524C 323F34 00105 LD (CBxx-offset),A ;in den Programm-Text 00106 524F C1 00107 POP BC ;Register zurück 5250 F1 00108 POP AF 5251 23 00109 INC HL ;PC neu setzen 5252 E3 00110 EX (SP),HL ;und HL zurück 5253 37 00111 SCF ;für invertiert!!! 5254 CB10 00112 RL B ;und rotieren 5255 00113 CBxx EQU $-1 ;10-17 für Register B-A 5256 C3AB06 00114 ab JP pramoff ;weiter im Programm 00115 00116 00117 ;*************************************** 00118 ;* illegaler Opcode: erstes Byte DD/FD * 00119 ;*************************************** 00120 5259 FECB 00121 ddfd CP 0cbh ;danach CBh? 525B 2828 00122 JR Z,ddfdcb ;ja 525D 326834 00123 LD (ersatz-offset),A ;in den Text 5260 FE26 00124 CP 26h ;"LD hX/Y, konstante"? 5262 2807 00125 JR Z,ldkon ;ja 5264 FE2E 00126 CP 2eh ;"LD IX/Y, konstante"? 5266 2803 00127 JR Z,ldkon ;ja 00128 5268 AF 00129 XOR A ;keine Konstante; NOP 5269 1802 00130 JR weiter 00131 00132 ; Konstante nach MSB/LSB von IX/Y 00133 526B 23 00134 ldkon INC HL ; Zeiger auf Konstante 526C 7E 00135 LD A,(HL) ;diese laden 00136 526D 326934 00137 weiter LD (konst-offset),A ;u. in den Text 5270 78 00138 LD A,B ;DD/FD zurück 5271 326534 00139 LD (ddfd1-offset),A ;setzen 5274 326B34 00140 LD (ddfd2-offset),A 00141 5277 C1 00142 POP BC ;alle Register zurück 5278 F1 00143 POP AF 5279 23 00144 INC HL ;PC neu 527A E3 00145 EX (SP),HL ;HL zurück 00146 527B DDE5 00147 ddfd1 PUSH IX ;bzw. IY 527D E3 00148 EX (SP),HL ;nach HL 527E 7F 00149 ersatz LD A,A ;Operation ausführen 527F 00 00150 konst NOP ;evtl. Konstante 5280 E3 00151 EX (SP),HL ;neues IX/Y zurück 5281 DDE1 00152 ddfd2 POP IX ;bzw. IY 5283 18D1 00153 JR ab 00154 00155 00156 ;************************************* 00157 ;* DD/FD gefolgt von CB * 00158 ;* RLC/RRC/RL/RR/SLA/SRA/(SLIA)/SRL, * 00159 ;* (IX/Y+d),B/C/D/E/H/L/A * 00160 ;************************************* 00161 5285 78 00162 ddfdcb LD A,B ;DD/FD zurück 5286 32C034 00163 LD (ddfd3-offset),A ;setzen 5289 32C534 00164 LD (ddfd4-offset),A 528C 23 00165 INC HL ;Zeiger auf Offset 528D 7E 00166 LD A,(HL) ;"d" aus (IX/Y+d) laden 528E 32C234 00167 LD (offs1-offset),A ;setzen 5291 32C734 00168 LD (offs2-offset),A 5294 23 00169 INC HL ;Zeiger auf Operation 00170 00171 ; Lade-Befehl errechnen und in den Text 00172 5295 7E 00173 LD A,(HL) ;Befehl laden 5296 E607 00174 AND 7 ;nur die Bits 0-2 5298 3C 00175 INC A ;+1 5299 47 00176 LD B,A ;als Zähler 529A 3E3E 00177 LD A,3eh ;Opcode 46h-7eh erzeugen 00178 529C C608 00179 loop1 ADD A,8 ;(46/4e/56/5e/66/6e/7e) 529E 10FC 00180 DJNZ loop1 ;=LD B/C/D/E/H/L/A, (IX..) 52A0 32C634 00181 LD (lade-offset),A ;setzen 00182 00183 ; Rotations-/Schiebe-Befehl erzeugen 00184 52A3 7E 00185 LD A,(HL) 52A4 E6F8 00186 AND 0f8h ;die Bits 0-2 löschen 52A6 0F 00187 RRCA ;und raus rotieren 52A7 0F 00188 RRCA 52A8 0F 00189 RRCA 52A9 3C 00190 INC A ;+1 52AA 47 00191 LD B,A ;als Zähler 52AB 3EFE 00192 LD A,0feh ;6/e/16/le/26/2e/3e=RLC, 00193 52AD C608 00194 loop2 ADD A,8 ;RRC,RL,RR,SLA,SRA,SRL 52AF 10FC 00195 DJNZ loop2 ;(u. RES/SET x) 00196 52B1 48 00197 LD C,B ;NOP erzeugen (für reta) 00198 52B2 FE36 00199 CP 36h ;SLIA? 52B4 200B 00200 JR NZ,noSLIA ;nein 00201 00202 ; SLIA (IX/Y+d) oder SLIA (IX/Y+d),r 00203 52B6 0637 00204 LD B,37h ;SCF erzeugen 52B8 7E 00205 LD A,(HL) ;SLIA (IX/Y+d)? 52B9 FE36 00206 CP 36h 52BB 2002 00207 JR NZ,nopro ;nein, kein Problem 52BD 0EC9 00208 LD C,0c9h ;RET für reta erzeugen 00209 52BF 3E16 00210 nopro LD A,16h ;RL erzeugen (statt SLIA) 00211 52C1 32C334 00212 noSLIA LD (opera-offset),A ;setzen 52C4 78 00213 LD A,B ;SCF oder NOP 52C5 32BF34 00214 LD cflag-offset),A ;setzen 52C8 79 00215 LD A,C ;RET oder NOP 52C9 32C434 00216 LD (reta-offset),A ;setzen 00217 52CC C1 00218 POP BC ;Register zurück 52CD F1 00219 POP AF 52CE 23 00220 INC HL ;PC korrigieren 52CF E3 00221 EX (SP),HL ;und HL zurück 00222 52D0 CDBF34 00223 CALL cflag-offset ;Operation ausführen 52D3 1881 00224 JR ab 00225 00226 ; Unterprogramm; Operation simulieren 00227 52D5 00 00228 cflag NOP ;oder SCF 00229 52D6 00 00230 ddfd3 NOP ;DD o. FD für IX/Y 52D7 CB 00231 DB 0cbh ;immer CBh 52D8 00 00232 offs1 NOP ;Offset d (IX/Y+d) 52D9 00 00233 opera NOP ;Operationsanweisung 00234 52DA 00 00235 reta NOP ;RETurn bei SLIA (IX/Y+d) 00236 52DB 00 00237 ddfd4 NOP ;DD/FD für IX/Y 52DC 7F 00238 lade LD A,A ;Ladebefehl 52DD 00 00239 offs2 NOP ;Offset (s. offs1) 52DE C9 00240 RET 00241 52DF 00242 ende EQU $ 00243 00244 5200 00245 END start1 hett seggt = plattdeutsch oder auch umgangssprachlicher Ausdruck für "hat gesagt" |